package com.example.mvvmrxjavaokhttpretrofit.net.rx;

import android.content.Context;


import com.example.mvvmrxjavaokhttpretrofit.net.RestCreator;
import com.example.mvvmrxjavaokhttpretrofit.net.RestService;
import com.example.mvvmrxjavaokhttpretrofit.utils.RdRequestHeadsParamsUtil;

import java.io.File;
import java.util.Map;
import java.util.WeakHashMap;

import io.reactivex.Observable;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;


public final class RxRestClient {

    private final WeakHashMap<String, Object> PARAMS;
    private final WeakHashMap<String, Object> HEADERS_PARAMS;
    private final String URL;
    private final RequestBody BODY;
    //    private final LoaderStyle LOADER_STYLE;
    private final File FILE;
    private final Context CONTEXT;

//    RxRestClient(String url,
//                 WeakHashMap<String, Object> params,
//                 RequestBody body,
//                 File file,
//                 Context context) {
//        this.URL = url;
//        this.PARAMS = params;
//        this.BODY = body;
//        this.FILE = file;
//        this.CONTEXT = context;
////        this.LOADER_STYLE = loaderStyle;
//    }

    RxRestClient(RxRestClientBuilder builder) {
        this.URL = builder.mUrl;
        this.PARAMS = builder.PARAMS;
        this.HEADERS_PARAMS = builder.HEADERS_PARAMS;
        this.BODY = builder.mBody;
        this.FILE = builder.mFile;
        this.CONTEXT = builder.mContext;
//        this.LOADER_STYLE = loaderStyle;
    }

    public static RxRestClientBuilder builder() {
        return new RxRestClientBuilder();
    }

    private Observable<ResponseBody> request(HttpMethod method) {
        final RestService service = RestCreator.getRestService();
        Observable<ResponseBody> observable = null;

        switch (method) {
            case GET:
                observable = service.get(URL, PARAMS);
                break;
            case POST:
                observable = service.post(URL, PARAMS);
                break;
            case POST_HEADERS:
                observable = service.postHeaders(URL, PARAMS, HEADERS_PARAMS);
                break;
            case POST_RAW:
                observable = service.postRaw(URL, BODY);
                break;
            case PUT:
                observable = service.put(URL, PARAMS);
                break;
            case PUT_RAW:
                observable = service.putRaw(URL, BODY);
                break;
            case DELETE:
                observable = service.delete(URL, PARAMS);
                break;
            case UPLOAD:
                Map<String, RequestBody> map = new WeakHashMap<>();
                //遍历map中所有参数到builder
                if (PARAMS != null) {
                    for (String key : PARAMS.keySet()) {
                        map.put(key, RequestBody.create(null, (String) PARAMS.get(key)));
                    }
                }
                final RequestBody requestBody =
                        RequestBody.create(MediaType.parse(MultipartBody.FORM.toString()), FILE);
                final MultipartBody.Part body =
                        MultipartBody.Part.createFormData("file", FILE.getName(), requestBody);
                observable = service.upload(URL,map,body);
                break;
            default:
                break;
        }

        return observable;
    }

    public final Observable<ResponseBody> get() {
        return request(HttpMethod.GET);
    }

    public final Observable<ResponseBody> post() {
        if (BODY == null) {
            return request(HttpMethod.POST);
        } else {
            if (!PARAMS.isEmpty()) {
                throw new RuntimeException("params must be null!");
            }
            return request(HttpMethod.POST_RAW);
        }
    }

    public final Observable<ResponseBody> postHeaders() {
        if (BODY == null) {
            return request(HttpMethod.POST_HEADERS);
        } else {
            if (!PARAMS.isEmpty()) {
                throw new RuntimeException("params must be null!");
            }
            return request(HttpMethod.POST_RAW);
        }
    }

    public final Observable<ResponseBody> put() {
        if (BODY == null) {
            return request(HttpMethod.PUT);
        } else {
            if (!PARAMS.isEmpty()) {
                throw new RuntimeException("params must be null!");
            }
            return request(HttpMethod.PUT_RAW);
        }
    }

    public final Observable<ResponseBody> delete() {
        return request(HttpMethod.DELETE);
    }

    public final Observable<ResponseBody> upload() {
        return request(HttpMethod.UPLOAD);
    }

    public final Observable<ResponseBody> download() {
        return RestCreator.getRestService().download(URL, PARAMS);
    }

    public static class RxRestClientBuilder {

        private final WeakHashMap<String, Object> PARAMS = new WeakHashMap<>();
        private final WeakHashMap<String, Object> HEADERS_PARAMS = new WeakHashMap<>();
        private String mUrl = null;
        private RequestBody mBody = null;
        private Context mContext = null;
        //    private LoaderStyle mLoaderStyle = null;
        private File mFile = null;

        RxRestClientBuilder() {
        }

        public final RxRestClientBuilder url(String url) {
            this.mUrl = url;
            return this;
        }

        public final RxRestClientBuilder params(WeakHashMap<String, Object> params) {
            PARAMS.putAll(params);
            return this;
        }

        public final RxRestClientBuilder param(String key, Object value) {
            PARAMS.put(key, value);
            return this;
        }

        public final RxRestClientBuilder headersParam(String key, Object value) {
            HEADERS_PARAMS.put(key, value);
            return this;
        }

        public final RxRestClientBuilder file(File file) {
            this.mFile = file;
            return this;
        }

        public final RxRestClientBuilder file(String file) {
            this.mFile = new File(file);
            return this;
        }

        public final RxRestClientBuilder raw(String raw) {
            this.mBody = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), raw);
            return this;
        }

        public final RxRestClientBuilder loader(Context context) {
            this.mContext = context;
//        this.mLoaderStyle = style;
            return this;
        }

//    public final RxRestClientBuilder loader(Context context) {
//        this.mContext = context;
//        this.mLoaderStyle = LoaderStyle.BallClipRotatePulseIndicator;
//        return this;
//    }

        @SuppressWarnings("unchecked")
        public final RxRestClient build() {
            PARAMS.putAll(RdRequestHeadsParamsUtil.getRequestHeadsParams());
//            return new RxRestClient(mUrl, PARAMS, mBody, mFile, mContext);
            return new RxRestClient(this);
        }
    }
}
